/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.log;

import cn.easyplatform.lang.stream.StringWriter;
import cn.easyplatform.web.WebApps;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.util.Transform;
import org.apache.logging.log4j.util.Strings;

import java.io.PrintWriter;
import java.io.Serializable;

/**
 * @Author: <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @Description:
 * @Since: 2.0.0 <br/>
 * @Date: Created in 2019/11/6 9:24
 * @Modified By:
 */
class ConsoleAppender extends AbstractAppender {

    private static final String REGEXP = Strings.LINE_SEPARATOR.equals("\n") ? "\n" : Strings.LINE_SEPARATOR + "|\n";

    private String projectId;

    private String[] target;

    private boolean isApi;

    private StringBuilder sb = new StringBuilder(1024);

    ConsoleAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions, Property[] properties) {
        super(name, filter, layout, ignoreExceptions, properties);
    }

    public ConsoleAppender setEnv(String projectId, String userId) {
        this.projectId = projectId;
        this.target = new String[]{userId};
        return this;
    }

    public ConsoleAppender setApi(boolean isApi) {
        this.isApi = isApi;
        return this;
    }

    @Override
    public void append(LogEvent event) {
        sb.setLength(0);
        if (event.getLevel() == Level.DEBUG) {
            sb.append("<span size=\"1.5\" color=\"#339933\">");
            sb.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel())));
            sb.append("</font>");
        } else if (event.getLevel() == Level.WARN) {
            sb.append("<font size=\"1.5\" color=\"#993300\">");
            sb.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel())));
            sb.append("</font>");
        } else {
            sb.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel())));
        }
        sb.append(Strings.LINE_SEPARATOR);
        if (!isApi) {
            String escapedLogger = Transform.escapeHtmlTags(StringUtils.substringAfterLast(event.getLoggerName(), "."));
            sb.append("<span class=\"z-a\">");
            sb.append(escapedLogger);
            sb.append("</span>");
            sb.append(Strings.LINE_SEPARATOR);
        }
        sb.append((Transform.escapeHtmlTags(event.getMessage().getFormattedMessage()).replaceAll(REGEXP, "<br />")));
        sb.append("</br>");
        if (event.getThrown() != null) {
            sb.append("<font size=\"1.5\" color=\"red\">");
            StringBuilder tmp = new StringBuilder();
            StringWriter w = new StringWriter(tmp);
            PrintWriter pw = new PrintWriter(w, true);
            event.getThrown().printStackTrace(pw);
            String[] items = tmp.toString().split("\\\n");
            for (int i = 0; i < items.length; i++) {
                sb.append(i + 1).append(" ").append(items[i]);
                sb.append("</br>");
            }
            w = null;
            pw = null;
            sb.append("</font>");
            sb.append("</br>");
        }
        WebApps.me().publish(projectId, target, new cn.easyplatform.spi.listener.event.LogEvent(sb.toString()));
    }
}
